package com.eyas.im.client.nio.handler;

import com.eyas.im.client.IMClient;
import com.eyas.im.client.SocketClientHandler;
import com.eyas.im.client.TaskCompleteFuture;
import com.eyas.im.client.WriteCallbackFunction;
import com.eyas.im.protocol.decoder.Decoder;
import com.eyas.im.protocol.encoder.Encoder;
import com.eyas.im.protocol.protocol.Protocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

public abstract class AbstractSocketClientHandler<T extends Protocol<?>> extends SocketClientIOEventHandler implements SocketClientHandler<T> {
    private final static Logger logger = LoggerFactory.getLogger(AbstractSocketClientHandler.class);
    private Encoder<T> encoder;
    private Decoder<T> decoder;
    private IMClient observer;

    protected AbstractSocketClientHandler(Encoder<T> encoder, Decoder<T> decoder, int bufferCapacity) {
        super(bufferCapacity);
        this.encoder = encoder;
        this.decoder = decoder;
    }

    @Override
    public final TaskCompleteFuture write(T sendData, WriteCallbackFunction writeCallback) throws IOException {
        byte[] bytes = this.encoder.encode(sendData);
        TaskCompleteFuture taskCompleteFuture = new TaskCompleteFuture(writeCallback);
        this.pushWriteBytes(taskCompleteFuture, bytes);
        return taskCompleteFuture;
    }

    /**
     * socketChannel READ事件获取到数据
     *
     * @param bytes
     */
    public final void onDataRecieved(byte[] bytes) {
        try {
            T result = this.decoder.decode(bytes);
            this.onDataDecode(result);
        } catch (IOException e) {
            logger.error("解码失败", e);
        }
    }

    @Override
    public final void flush() {
        this.maskWrite();
    }
    /**
     * 用于绑定socketKey和SocketChannel，不需要用户自己调用
     *
     * @param attchments
     */
    public final void attch(Object... attchments) {
        this.bind((SelectionKey) attchments[0], (SocketChannel) attchments[1]);
    }

    public final void shutdown() {
        this.observer.shutdwonGraceful();
    }

    public final IMClient observer() {
        return this.observer;
    }

    public final void observer(IMClient imClient) {
        this.observer = imClient;
    }
}
